#include <iterator>
#include <tuple>
#include <utility>
#include <functional>

#ifndef ENOR
#define ENOR

// goal: make enor<H> a valid statement in main.
// and have overrideable specializations for enor<H>::first, enor<H>::next, enor<H>::current, enor<H>::end.
// after this, stl-like algorithms are implemented for general purpose useage of enors (instead of inputiterators..)
// as if someone would ever want that..

namespace ph{

template<class E>
class enor{
public:
	// Stuff to make it look like textbook!
	virtual void first() = 0;
	virtual void next() = 0;
	virtual const E& current() const = 0;
	virtual const bool end() const = 0;
	typedef E Type;
};

template<class EnorType>
typename EnorType::Type sum(EnorType& t, typename EnorType::Type&& zero){
	typename EnorType::Type s = zero;
	t.first();
	while(!t.end()){
		s += t.current();
		t.next();
	}
	return s;
}

template<class EnorType, class Functor>
unsigned count(EnorType& t, Functor beta){
	unsigned c = 0;
	t.first();
	while(!t.end()){
		c += beta(t.current());
		t.next();
	}
	return c;
}

template<class EnorType, class Functor>
auto max(EnorType& t, Functor f) -> std::pair<decltype( f(t.current())), typename EnorType::Type>{ // (max, elem)
	decltype( f(t.current()) ) max;
	typename EnorType::Type elem;
	t.first();
	max=f(t.current());
	elem=t.current();
	t.next();
	while(!t.end()){
		if(f( t.current() ) > max){
			max=f(t.current());
			elem=t.current();
		}
		t.next();
	}
	return std::make_pair(max, elem);
}

template<class EnorType, class Functor>
typename EnorType::Type select(EnorType& t, Functor beta){
	t.first();
	while(!beta(t.current())){
		t.next();
	}
	return t.current();
}

template<class EnorType, class Functor>
auto search(EnorType& t, Functor beta) -> std::pair<bool, decltype( t.current() )> {
	t.first();
	bool l = false;
	decltype(t.current()) elem;
	while(!l && !t.end()){
		elem = t.current();
		l = beta(elem);
		t.next();
	}
	return std::make_pair(l, elem);
}

template<class EnorType, class E, class H>
std::tuple<bool, H, E> max_if(EnorType& t, bool (*beta)(E), H (*f)(H)){
	bool l = false;
	H max;
	E elem;

	t.first();
	while(!t.end()){
		if(beta(t.current())){
			if(l){
				if(f(t.current())>max){
					max = f(t.current());
					elem = t.current();
				}
			}
			else{
				l = true;
				max = f(t.current());
				elem = t.current();
			}
		}
		t.next();
	}
	return std::make_tuple(l, max, elem);
}

// Textbook algorithms over, commence STL!



} //namespace
#endif